﻿//#define _CRT_SECURE_NO_WARNINGS
// C/C++ 标准库学习网站：https://legacy.cplusplus.com
// C/C++ 参考学习网站：https://zh.cppreference.com/w/cpp
// C/C++ 微软(Visual Studio)中文学习网站：https://learn.microsoft.com/zh-cn/cpp/cpp/?view=msvc-170
// OpenGl 学习网站：https://docs.gl/
#include "common.h"
//#include <iostream>

#include "MusicReader.h"
static std::mutex filter_param_mutex;
static bool is_init_filters = false;

void MusicReader::init_filters(AVChannelLayout layout, int sample_rate, AVSampleFormat sample_fmt)
{
    is_init_filters = true;
    free_filters();

    std::lock_guard<std::mutex> lock(filter_param_mutex);
    const AVFilter* buffersrc = avfilter_get_by_name("abuffer");
    const AVFilter* buffersink = avfilter_get_by_name("abuffersink");
    if (!buffersrc || !buffersink) {
        qDebug() << "Could not find the abuffer or abuffersink filter";
        return;
    }

    AVFilterInOut* outputs = avfilter_inout_alloc();
    AVFilterInOut* inputs = avfilter_inout_alloc();
    if (!outputs || !inputs) {
        qDebug() << "Could not allocate filter inputs or outputs";
        return;
    }

    AVRational time_base = { 1, sample_rate };
    char args[512];

    filter_graph = avfilter_graph_alloc();
    if (!filter_graph) {
        qDebug() << "Could not allocate filter graph";
        return;
    }

    snprintf(args, sizeof(args),
        "sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d:channel_layout=0x%" PRIx64,
        sample_rate, av_get_sample_fmt_name(sample_fmt), layout.nb_channels, time_base.num, time_base.den, layout.u.mask);

    enum AVSampleFormat out_sample_fmts[] = { sample_fmt, AV_SAMPLE_FMT_NONE };

    int ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, nullptr, filter_graph);
    if (ret < 0) {
        char errbuf[128];
        av_strerror(ret, errbuf, sizeof(errbuf));
        qDebug() << "Failed to create abuffer filter: " << errbuf;
        goto end;
    }
    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", nullptr, nullptr, filter_graph);
    if (ret < 0) {
        char errbuf[128];
        av_strerror(ret, errbuf, sizeof(errbuf));
        qDebug() << "Failed to create abuffersink filter: " << errbuf;
        goto end;
    }

    //enum AVSampleFormat out_sample_fmts[] = { sample_fmt, AV_SAMPLE_FMT_NONE };
    //av_opt_set_int_list(buffersink_ctx, "sample_fmts", out_sample_fmts, -1, AV_OPT_SEARCH_CHILDREN);

    // Replace av_opt_set_int_list with a loop to set the sample formats manually
    //for (int i = 0; out_sample_fmts[i] != AV_SAMPLE_FMT_NONE; ++i) {
    //    // 替换循环，直接设置完整格式数组
    //    ret = av_opt_set_bin(buffersink_ctx, "sample_fmts",
    //        (uint8_t*)out_sample_fmts,
    //        sizeof(AVSampleFormat) * (i + 1),
    //        AV_OPT_SEARCH_CHILDREN);
    //    if (ret < 0) {
    //        char errbuf[128];
    //        av_strerror(ret, errbuf, sizeof(errbuf));
    //        qDebug() << "Failed to set sample format: " << errbuf;
    //        //goto end;
    //        continue;
    //    }
    //}

    char filter_desc[1024];
    snprintf(filter_desc, sizeof(filter_desc),
        "equalizer=f=62:t=q:w=1:g=%.1f,"
        "equalizer=f=125:t=q:w=1:g=%.1f,"
        "equalizer=f=250:t=q:w=1:g=%.1f,"
        "equalizer=f=500:t=q:w=1:g=%.1f,"
        "equalizer=f=1000:t=q:w=1:g=%.1f,"
        "equalizer=f=2000:t=q:w=1:g=%.1f,"
        "equalizer=f=4000:t=q:w=1:g=%.1f,"
        "equalizer=f=8000:t=q:w=1:g=%.1f,"
        "equalizer=f=16000:t=q:w=1:g=%.1f",
        my_filters.f62, my_filters.f125, my_filters.f250,
        my_filters.f500, my_filters.f1000, my_filters.f2000,
        my_filters.f4000, my_filters.f8000, my_filters.f16000
    );

    outputs->name = av_strdup("in");
    outputs->filter_ctx = buffersrc_ctx;
    outputs->pad_idx = 0;
    outputs->next = nullptr;

    inputs->name = av_strdup("out");
    inputs->filter_ctx = buffersink_ctx;
    inputs->pad_idx = 0;
    inputs->next = nullptr;

    ret = avfilter_graph_parse_ptr(filter_graph, filter_desc, &inputs, &outputs, nullptr);
    if (ret < 0) {
        char errbuf[128];
        av_strerror(ret, errbuf, sizeof(errbuf));
        qDebug() << "Failed to parse filter description: " << filter_desc << "。" << errbuf;
        goto end;
    }

    ret = avfilter_graph_config(filter_graph, nullptr);
    if (ret < 0) {
        char errbuf[128];
        av_strerror(ret, errbuf, sizeof(errbuf));
        qDebug() << "Failed to config filter graph: " << errbuf;
        goto end;
    }

end:
    avfilter_inout_free(&inputs);
    avfilter_inout_free(&outputs);
    is_init_filters = false;
}

//void MusicReader::init_filters(AVChannelLayout layout, int sample_rate, AVSampleFormat sample_fmt)
//{
//    free_filters();
//
//    const AVFilter* buffersrc = avfilter_get_by_name("abuffer");
//    const AVFilter* buffersink = avfilter_get_by_name("abuffersink");
//    AVFilterInOut* outputs = avfilter_inout_alloc();
//    AVFilterInOut* inputs = avfilter_inout_alloc();
//    AVRational time_base = {1, sample_rate};
//    char args[512];
//
//    filter_graph = avfilter_graph_alloc();
//
//    // 分配源滤镜和汇滤镜的上下文
//    buffersrc_ctx = avfilter_graph_alloc_filter(filter_graph, buffersrc, "in");
//    buffersink_ctx = avfilter_graph_alloc_filter(filter_graph, buffersink, "out");
//    if (!buffersrc_ctx || !buffersink_ctx) {
//        qDebug() << "Could not allocate a buffer source or sink";
//        return;
//    }
//
//    // 配置源滤镜参数
//    snprintf(args, sizeof(args),
//             "sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d:channel_layout=0x%d" PRIx64,
//             sample_rate, av_get_sample_fmt_name(sample_fmt), layout.nb_channels, time_base.num, time_base.den, layout.u.mask);
//
//    int ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, nullptr, filter_graph);
//    if (ret < 0) {
//        char errbuf[128];
//        av_strerror(ret, errbuf, sizeof(errbuf));
//        qDebug() << "Failed to create abuffer filter。" << errbuf;
//        goto end;
//    }
//    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", nullptr, nullptr, filter_graph);
//    if (ret < 0) {
//        char errbuf[128];
//        av_strerror(ret, errbuf, sizeof(errbuf));
//        qDebug() << "Failed to create abuffersink filter" << errbuf;
//        goto end;
//    }
//
//    // 构建 equalizer filter chain
//    /// 低频: 60Hz, 140Hz, 350Hz；
//    /// 中频: 660kHz, 1kHz, 3kHz；
//    /// 高频: 6kHz, 10kHz, 12kHz, 15kHz
//
//    char filter_desc[1024];
//    {
//        std::lock_guard<std::mutex> lock(filter_param_mutex);
//        snprintf(filter_desc, sizeof(filter_desc),
//            "equalizer=f=60:t=q:w=1:g=%.1f,"
//            "equalizer=f=140:t=q:w=1:g=%.1f,"
//            "equalizer=f=350:t=q:w=1:g=%.1f,"
//            "equalizer=f=660:t=q:w=1:g=%.1f,"
//            "equalizer=f=1000:t=q:w=1:g=%.1f,"
//            "equalizer=f=3000:t=q:w=1:g=%.1f,"
//            "equalizer=f=6000:t=q:w=1:g=%.1f,"
//            "equalizer=f=10000:t=q:w=1:g=%.1f,"
//            "equalizer=f=12000:t=q:w=1:g=%.1f,"
//            "equalizer=f=15000:t=q:w=1:g=%.1f",
//            my_filters.f60, my_filters.f140, my_filters.f350,
//            my_filters.f660, my_filters.f1000, my_filters.f3000,
//            my_filters.f6000, my_filters.f10000, my_filters.f12000, my_filters.f15000
//        ); // .1f% 表示增益的响度，可自定义范围，比如 -12db ~ 12db
//    }
//
//    // 连接 abuffer -> equalizer(低) -> equalizer(中) -> equalizer(高) -> abuffersink
//    outputs->name = av_strdup("in");
//    outputs->filter_ctx = buffersrc_ctx;
//    outputs->pad_idx = 0;
//    outputs->next = nullptr;
//
//    inputs->name = av_strdup("out");
//    inputs->filter_ctx = buffersink_ctx;
//    inputs->pad_idx = 0;
//    inputs->next = nullptr;
//
//    ret = avfilter_graph_parse_ptr(filter_graph, filter_desc, &inputs, &outputs, nullptr);
//    if (ret < 0) {
//        char errbuf[128];
//        av_strerror(ret, errbuf, sizeof(errbuf));
//        qDebug() << "Failed to parse filter description: " << filter_desc << "。" << errbuf;
//        qDebug() << "Failed to parse filter graph";
//        goto end;
//    }
//
//    ret = avfilter_graph_config(filter_graph, nullptr);
//    if (ret < 0) {
//        char errbuf[128];
//        av_strerror(ret, errbuf, sizeof(errbuf));
//        qDebug() << "Failed to config filter graph." << errbuf;
//        //goto end;
//    }
//
//end:
//    avfilter_inout_free(&inputs);
//    avfilter_inout_free(&outputs);
//}

void MusicReader::free_filters()
{
    std::lock_guard<std::mutex> lock(filter_param_mutex);
    if (buffersrc_ctx) {
        avfilter_free(buffersrc_ctx);
        buffersrc_ctx = nullptr;
    }
    if (buffersink_ctx) {
        avfilter_free(buffersink_ctx);
        buffersink_ctx = nullptr;
    }
    if (filter_graph) {
        // 需要在 avfilter_graph_free 之前释放 buffersrc_ctx 和 buffersink_ctx
        avfilter_graph_free(&filter_graph);
        filter_graph = nullptr;
    }
}

AVFrame* MusicReader::convert_filters_frame(AVFrame* frame)
{
    while (is_init_filters || !filter_graph || !buffersrc_ctx || !buffersink_ctx)
        continue;

    std::lock_guard<std::mutex> lock(filter_param_mutex);

    // 将音频帧发送到滤镜链的输入
    int ret = av_buffersrc_add_frame(buffersrc_ctx, frame);
    if (ret < 0) {
        // 如果发送帧失败，打印错误信息并返回 nullptr
        char errbuf[128];
        av_strerror(ret, errbuf, sizeof(errbuf));
        qDebug() << "Error while feeding the audio frame to the filter graph: " << errbuf;
        return nullptr;
    }

    // 分配一个用于存储处理后音频帧的 AVFrame
    AVFrame* filtered_frame = av_frame_alloc();
    if (!filtered_frame) {
        // 如果分配 AVFrame 失败，打印错误信息并跳转到 end 标签
        qDebug() << "Failed to allocate filter frame";
        goto end;
    }

    // 从滤镜链的输出接收处理后的音频帧
    ret = av_buffersink_get_frame(buffersink_ctx, filtered_frame);
    if (ret == AVERROR(EAGAIN)) {
        // 如果滤镜链需要更多的输入帧才能生成输出帧，打印信息并跳转到 end 标签
        qDebug() << "Need more input frames";
        goto end;
    }
    else if (ret < 0) {
        // 如果接收帧时发生其他错误，打印错误信息并跳转到 end 标签
        char errbuf[128];
        av_strerror(ret, errbuf, sizeof(errbuf));
        qDebug() << "Error while receiving the audio frame from the filter graph: " << errbuf;
        goto end;
    }

    // 处理过滤后的音频帧
    // 这里可以对 filtered_frame 进行进一步处理，例如保存或播放
    // ...

    // 返回处理后的音频帧
    return filtered_frame;

end:
    // 释放 filtered_frame 中引用的资源
    av_frame_unref(filtered_frame);
    // 释放 filtered_frame 结构体本身
    av_frame_free(&filtered_frame);
    // 返回 nullptr，表示未成功获取过滤后的音频帧
    return nullptr;
}

